//
// CNetOutPin.cpp
//

#include "stdafx.h"
#include "GlobalDefs.h"
#include <streams.h>
#include "CFilterNetReceiver.h"
#include "CNetOutPin.h"

///////////////////////////////////////////////////////////////////////////////
CNetOutPin::CNetOutPin(CFilterNetReceiver *inFilter, HRESULT *phr, LPCWSTR pName) :
CBaseOutputPin(NAME("Net_Stream"), inFilter, &inFilter->mFilterLock, phr, pName)
{
	mFilter = inFilter;
	mPreferredMt.InitMediaType();

	// Test
/*	mPreferredMt.SetType(&MEDIATYPE_Video);
	mPreferredMt.SetSubtype(&MEDIASUBTYPE_RGB24);
	mPreferredMt.SetFormatType(&FORMAT_VideoInfo);
	mPreferredMt.SetTemporalCompression(FALSE);
	VIDEOINFOHEADER     info;
	ZeroMemory(&info, sizeof(VIDEOINFOHEADER));
	info.AvgTimePerFrame = 400000;
	info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	info.bmiHeader.biWidth  = 360;
	info.bmiHeader.biHeight = 288;
	info.bmiHeader.biBitCount  = 24;
	info.bmiHeader.biSizeImage = 360 * 288 * 3;
	info.bmiHeader.biCompression = 0;
	info.bmiHeader.biPlanes = 1;
	mPreferredMt.SetFormat((BYTE*)&info, sizeof(VIDEOINFOHEADER));
	mPreferredMt.SetSampleSize(info.bmiHeader.biSizeImage);*/
}

CNetOutPin::~CNetOutPin()
{
}

void CNetOutPin::SetupMediaType(long inType, char * inFormat, long inLength)
{
	if (inType == PT_VideoMediaType)
	{
		mPreferredMt.SetType(&MEDIATYPE_Video);
		mPreferredMt.SetFormatType(&FORMAT_VideoInfo);
		// Determine the video subtype
		VIDEOINFOHEADER * pvi = (VIDEOINFOHEADER *) inFormat;
		const GUID subtype = GetBitmapSubtype(&pvi->bmiHeader);
		mPreferredMt.SetSubtype(&subtype);
		
		// Verify image size
		pvi->bmiHeader.biSizeImage = pvi->bmiHeader.biWidth * pvi->bmiHeader.biHeight 
			* pvi->bmiHeader.biBitCount / 8;
		mPreferredMt.SetFormat((BYTE*)inFormat, inLength);
		mPreferredMt.SetSampleSize(pvi->bmiHeader.biSizeImage);
	}
	else
	{
		mPreferredMt.SetType(&MEDIATYPE_Audio);
		mPreferredMt.SetSubtype(&MEDIASUBTYPE_PCM);
		mPreferredMt.SetFormatType(&FORMAT_WaveFormatEx);
		
		// Verify sample size (one second)
		WAVEFORMATEX * wave = (WAVEFORMATEX *) inFormat;
		wave->nAvgBytesPerSec = wave->nSamplesPerSec * wave->nChannels
			* wave->wBitsPerSample / 8;
		mPreferredMt.SetFormat((BYTE*)inFormat, inLength);

		mFilter->SetAudioBytesPerSecond(wave->nAvgBytesPerSec);
	}
	
	mPreferredMt.SetTemporalCompression(FALSE);
}

HRESULT CNetOutPin::CheckMediaType(const CMediaType * inMediaType)
{
	if (*inMediaType == mPreferredMt)
	{
		return NOERROR;
	}
	return E_FAIL;
}

HRESULT CNetOutPin::DecideBufferSize(IMemAllocator * pAlloc, ALLOCATOR_PROPERTIES * pprop)
{
	ASSERT(pAlloc);
	ASSERT(pprop);
	HRESULT hr = NOERROR;

	// Determine sample size
	if (mPreferredMt.formattype == FORMAT_VideoInfo)
	{
		VIDEOINFOHEADER * info = (VIDEOINFOHEADER *) mPreferredMt.pbFormat;
		pprop->cbBuffer = info->bmiHeader.biSizeImage;
	}
	else
	{
		WAVEFORMATEX * info = (WAVEFORMATEX *) mPreferredMt.pbFormat;
		pprop->cbBuffer = info->nAvgBytesPerSec;
	}
	pprop->cBuffers  = 1;
	pprop->cbAlign   = 1;

	ASSERT(pprop->cbBuffer);

	ALLOCATOR_PROPERTIES Actual;
	hr = pAlloc->SetProperties(pprop, &Actual);
	if (FAILED(hr)) 
	{
		return hr;
	}

	ASSERT( Actual.cBuffers == 1 );

	if (pprop->cBuffers > Actual.cBuffers ||
		pprop->cbBuffer > Actual.cbBuffer) 
	{
		return E_FAIL;
	}
	return NOERROR;
}

HRESULT CNetOutPin::GetMediaType(int iPosition,CMediaType *pMediaType)
{
	if (iPosition == 0)
	{
		*pMediaType = mPreferredMt;
		return NOERROR;
	}
	return E_INVALIDARG;
}